package cn.turboinfo.fuyang.api.domain.mini.usecase.order;

import cn.turboinfo.fuyang.api.domain.common.handler.order.ServiceOrderDataFactory;
import cn.turboinfo.fuyang.api.domain.common.service.company.HousekeepingCompanyService;
import cn.turboinfo.fuyang.api.domain.common.service.division.DivisionService;
import cn.turboinfo.fuyang.api.domain.common.service.file.FileAttachmentService;
import cn.turboinfo.fuyang.api.domain.common.service.order.ServiceOrderService;
import cn.turboinfo.fuyang.api.domain.common.service.product.ProductService;
import cn.turboinfo.fuyang.api.domain.common.service.staff.HousekeepingStaffService;
import cn.turboinfo.fuyang.api.domain.common.service.user.UserTypeRelService;
import cn.turboinfo.fuyang.api.domain.common.usecase.AbstractUseCase;
import cn.turboinfo.fuyang.api.domain.util.IdCardUtils;
import cn.turboinfo.fuyang.api.domain.web.component.file.FileRefTypeConstant;
import cn.turboinfo.fuyang.api.entity.common.enumeration.user.UserType;
import cn.turboinfo.fuyang.api.entity.common.fo.company.ViewCompanyFO;
import cn.turboinfo.fuyang.api.entity.common.fo.order.ViewServiceOrderFO;
import cn.turboinfo.fuyang.api.entity.common.fo.staff.ViewStaffFO;
import cn.turboinfo.fuyang.api.entity.common.pojo.company.HousekeepingCompany;
import cn.turboinfo.fuyang.api.entity.common.pojo.file.FileAttachment;
import cn.turboinfo.fuyang.api.entity.common.pojo.order.ServiceOrder;
import cn.turboinfo.fuyang.api.entity.common.pojo.product.Product;
import cn.turboinfo.fuyang.api.entity.common.pojo.staff.HousekeepingStaff;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.UserTypeRel;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import net.sunshow.toolkit.core.qbean.helper.component.mapper.BeanMapper;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 服务订单详情
 *
 * @author hai
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MiniViewServiceOrderUseCase extends AbstractUseCase<MiniViewServiceOrderUseCase.InputData, MiniViewServiceOrderUseCase.OutputData> {

    private final ServiceOrderService serviceOrderService;

    private final ProductService productService;

    private final HousekeepingStaffService housekeepingStaffService;

    private final FileAttachmentService fileAttachmentService;

    private final HousekeepingCompanyService housekeepingCompanyService;

    private final DivisionService divisionService;

    private final UserTypeRelService userTypeRelService;

    private final ServiceOrderDataFactory serviceOrderDataFactory;

    @Override
    protected OutputData doAction(InputData inputData) {
        Long userId = inputData.getUserId();
        Long serviceOrderId = inputData.getServiceOrderId();

        ServiceOrder serviceOrder = serviceOrderService.getByIdEnsure(serviceOrderId);

        if (!Objects.equals(userId, serviceOrder.getUserId())) {
            List<UserTypeRel> userTypeRelList = userTypeRelService.findByUserId(userId);

            if (userTypeRelList.stream().noneMatch(userTypeRel -> {
                if (userTypeRel.getUserType() == UserType.Company) {
                    return Objects.equals(userTypeRel.getObjectId(), serviceOrder.getCompanyId());
                } else if (userTypeRel.getUserType() == UserType.Staff) {
                    return Objects.equals(userTypeRel.getObjectId(), serviceOrder.getStaffId());
                }
                return false;
            })) {
                throw new IllegalArgumentException("无权查看此订单");
            }
        }

        Product product = productService.getByIdEnsure(serviceOrder.getProductId());

        // 查询附件
        product.setImgList(fileAttachmentService.findByRefIdAndRefType(product.getId(), FileRefTypeConstant.PRODUCT_IMG)
                .stream().map(FileAttachment::getId).collect(Collectors.toList()));
        fileAttachmentService.findByRefIdAndRefType(product.getId(), FileRefTypeConstant.PRODUCT_VIDEO).forEach(fileAttachment -> {
            product.getVideoList().add(fileAttachment.getId());
            product.getVideoNameList().add(fileAttachment.getDisplayName());
        });
        HousekeepingStaff staff;
        if (serviceOrder.getStaffId() > 0) {
            staff = housekeepingStaffService.getByIdEnsure(serviceOrder.getStaffId());

            if (staff.getDisplayName().isBlank()) {
                staff.setDisplayName(staff.getName());
            }
            // 填充省份名称
            divisionService.getById(staff.getProvinceCode())
                    .ifPresent(division -> staff.setProvinceName(division.getAreaName()));

            // 设置年龄
            staff.setAge(IdCardUtils.countAge(staff.getIdCard()));
        } else {
            staff = null;
        }

        ViewStaffFO staffFO = null;

        if (staff != null) {
            staffFO = BeanMapper.map(staff, ViewStaffFO.class);
        }

        HousekeepingCompany company = housekeepingCompanyService.getByIdEnsure(serviceOrder.getCompanyId());

        serviceOrderDataFactory.maskInfo(serviceOrder);

        return OutputData.builder()
                .serviceOrder(BeanMapper.map(serviceOrder, ViewServiceOrderFO.class))
                .product(product)
                .staff(staffFO)
                .company(BeanMapper.map(company, ViewCompanyFO.class))
                .build();
    }

    @EqualsAndHashCode(callSuper = true)
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public static class InputData extends AbstractUseCase.InputData {

        /**
         * 用户编码
         */
        @NotNull(message = "用户ID不能为空")
        @Positive
        private Long userId;

        /**
         * 服务订单ID
         */
        @NotNull(message = "服务订单不能为空")
        @Positive
        private Long serviceOrderId;

    }

    @Getter
    @Setter
    @Builder
    public static class OutputData extends AbstractUseCase.OutputData {

        private ViewServiceOrderFO serviceOrder;

        private Product product;

        private ViewStaffFO staff;

        private ViewCompanyFO company;
    }
}
